package tree;

import java.util.Iterator;

import compiler.CompilerException;

import code.CodeList;
import code.TargetCode;
import lexer.Token;

/**
 * Syntax Tree Nodes.
 */
public interface Tree extends Iterable<Tree> {
	
	/**
	 * Get the i-th operand of the node.
	 * @param i The index of the operand.
	 * @return The i-th operand tree.
	 */
	Tree getOperand(int i);
	
	/**
	 * Set the i-th operand.
	 * @param i The index.
	 * @param t The operand tree.
	 */
	void setOperand(int i, Tree t);

	/**
	 * Get the number of operands this tree node can have.
	 * @return The number of operands.
	 */
	int getOperands();
	
	Tree[] getAllOperands();
	/**
	 * Get the parent node of this node.
	 * @return The parent
	 */
	Tree getParent();
	
	/**
	 * Set the parent of this node.
	 * Attention: Following contract has to be fulfilled:
	 * t.getOperand(i).getParent == t
	 * For all operands of a tree node.
	 * @param t The parent node to set this node to.
	 */
	void setParent(Tree t);

	/**
	 * Get the token of this node.
	 * @return The token.
	 */
	Token getToken();
	
	/**
	 * Return an iterator over the operands of this node.
	 * @return The iterator.
	 */
	Iterator<Tree> iterator();

	/**
	 * Return a string representation of the node.
	 * @return A string representation of the node.
	 */
	String toString();

	String nodeToString();
	
	/**
	 * Perform a pre name analysis phase (e.g. declares the method declaration)
	 * @param identScope
	 * @param methodScope
	 * @param classScope
	 * @throws NamingException
	 */
	void preAnalyzeNames(IdentifierScope identScope, 
			MethodScope methodScope, ClassScope classScope) throws NamingException;
	
	/**
	 * Perform name analysis on the program.
	 * @param identScope
	 * @param methodScope
	 * @param classScope
	 * @throws NamingException
	 */
	void analyzeNames(IdentifierScope identScope, 
			MethodScope methodScope, ClassScope classScope) throws NamingException;

	/**
	 * Compute the type of the node
	 * @return The type of the node 
	 * @throws TypingException
	 */
	Type computeType() throws TypingException;

	/**
	 * Get the local variable number of the variable this tree represents.
	 * @return The local variable number or -1 if this tree does not represent a variable.
	 */
	int getLocalVar();
	
	/**
	 * Return the number of the instance variable this node represents
	 * @return the instVar or -1 if it only a normal local Var
	 */
	int getInstVar();
	
	/**
	 * Return the number of instance variables of this class
	 * @return the number of InstVar
	 */
	int getNumberOfInstVar();
	
	/**
	 * Return the unique number that identifies this method
	 * @return the identity number
	 */
	int getMethodVar();
	
	/**
	 * Generate code for this node.
	 * @param code A code object to which new instructions can be added.
	 */
	void generateCode(CodeList code) throws CompilerException ;
	
	/**
	 * Generates the BytecodeFile (fills up TargetCode)
	 * @param targetCode
	 * @throws CompilerException 
	 */
	void generateProgramCode(TargetCode targetCode) throws CompilerException;
	
	Type expectSameType(Tree t1, Tree t2) throws TypingException;
	
	Type expectType(Tree t, Type ... ty) throws TypingException;
	
}
